<template>
  <div v-loading="loading" element-loading-text="加载中">
    <el-form ref="catePropertyForm" 
      :model="catePropertyForm" 
      :rules="formRules"
      label-position="right" 
      label-width="140px" 
      label-suffix="：">

      <div v-for="(item, index) in catePropertyForm.catePropertyList" :key="index">

        <template v-if="item.showFlag">

          <el-form-item :label="item.propName" :prop="item.prop">

            <!-- 文本 -->
            <template v-if="item.propInputType == 'text'">
              <el-input :ref="item.propId" v-model="item.propValue" class="width-350">

                <!-- 后置内容 -->
                <template v-if="item.textRule && item.textRule.appendTextRule" slot="append">
                  <template v-if="item.textRule.appendTextRule.appendInputType == 0">
                    <span>{{ item.textRule.appendTextRule.fixValue }}</span>
                  </template>

                  <template v-else-if="item.textRule.appendTextRule.appendInputType == 2">
                    <el-select v-model="item.additionalPropValueAndId" clearable filterable class="width-120">
                      <el-option v-for="(option, option_index) in item.textRule.appendTextRule.optionList" 
                        :key="option_index" 
                        :label="option.propValue" 
                        :value="option.propValueId + '@#' + option.propValue">
                      </el-option>
                    </el-select>
                  </template>

                </template>
              </el-input>
            </template>

            <!-- 日期时间 -->
            <template v-else-if="item.propInputType == 'datetime'">
              <el-date-picker :ref="item.propId" 
                v-model="item.propValue" 
                value-format="timestamp"
                :type="item.dateTimeRule.format === 'yearrange' ? 'monthrange' : item.dateTimeRule.format" 
                :format="item.dateTimeRule.format === 'yearrange' ? 'yyyy' : ''"
                class="width-350">
              </el-date-picker>
            </template>

            <!-- 图片 -->
            <template v-else-if="item.propInputType == 'image'">
              <div class="flex">
                <template v-for="(image, index) in item.imageList">
                  <div class="pic-bar mar-r-30" :key="index">
                    <div @click="deleteImgages(item, index)">
                      <svg-icon icon-class="close" class="close-icon font-16 noraml-hide active"/>
                    </div>
                    <img class="picture" :src="image + '?imageView2/1/w/200/h/200/q/100'"/>
                  </div>
                </template>

                <el-upload list-type="picture-card" 
                  action="/api/common/uploadFiles" 
                  name="files" 
                  v-loading="item.fileLoading" 
                  v-if="item.imageList.length < item.imageRule.maxCount"
                  :data="token" 
                  :limit="item.imageRule.maxCount"
                  :multiple="item.imageRule.maxCount > 1 ? true : false"
                  :show-file-list="false" 
                  :before-upload="(file) => beforeUpload(file, item)" 
                  :on-exceed="(file, fileList) => handleExceed(file, fileList, item.imageRule.maxCount)" 
                  :on-success="(res, file, fileList) => handleUploadSuccess(res, file, fileList, item)"
                  >
                  <i class="el-icon-plus"></i>
                </el-upload>
              </div>
            </template>

            <!-- 单选 -->
            <template v-else-if="item.propInputType == 'select'">
              <el-select :ref="item.propId" v-model="item.propValueAndId" clearable filterable class="width-350" @change="doSelectChange(), doCascadeShow(item)">

                <el-option v-for="(option, option_index) in item.selectRule.optionList" 
                  :key="option_index" 
                  :label="option.propValue" 
                  :value="option.propValueId + '@#' + option.propValue">
                </el-option>
              </el-select>
            </template>

            <!-- 多选 -->
            <template v-else-if="item.propInputType == 'multiSelect'">
              <el-select :ref="item.propId" v-model="item.multiPropValueIds" 
                multiple 
                :multiple-limit="item.multiSelectRule.multipleMaxNum" 
                clearable 
                filterable 
                class="width-350">

                <el-option v-for="(option, option_index) in item.multiSelectRule.optionList" 
                  :key="option_index" 
                  :label="option.propValue" 
                  :value="option.propValueId">
                </el-option>
              </el-select>
            </template>

            <template v-else>
              <span>未知的组件类型</span>
            </template>

          </el-form-item>

        </template>

      </div>
    </el-form>

    <el-button v-show="catePropertyForm.catePropertyList.length > 0" type="primary" class="btn" @click="doSave">保存</el-button>
  </div>
</template>

<script>
  import { getToken } from '@/utils/auth'
  import { getCateProperty } from '@/api/third/thirdGoods'

  export default {
    props: {
      // 平台类型
      platformType: {
        type: Number
      },
      // 店铺id
      shopId: {
        type: String
      },
      // 第三方分类id
      thirdCategoryId: {
        type: String
      }
    },
    watch: {
      thirdCategoryId(val) {
        const originData = this.$options.data()
        this.catePropertyForm = originData.catePropertyForm
        this.formRules = originData.formRules
        this.$refs['catePropertyForm'].clearValidate()
        console.log('222')
        if (val) {
          console.log('222 start')
          this.init()
        }
      }
    },
    data() {
      return {
        token: '',
        loading: false,
        // 表单规则
        formRules: {},
        // 类目属性表单
        catePropertyForm: {
          catePropertyList: []
        }
      }
    },
    created() {
      this.token = { accessToken: getToken() }
      // 初始化
      // this.initAfterHandle()
      console.log('created')
      if (!this.platformType || !this.shopId || !this.thirdCategoryId) return
      console.log('created init')
      this.init()
    },
    methods: {
      // 初始化
      init() {
        this.loading = true
        getCateProperty(this.platformType, this.shopId, this.thirdCategoryId).then(response => {
          this.loading = false
          if (response.isError) return
          this.catePropertyForm.catePropertyList = response.data
          this.initAfterHandle()
        })
      },
      // 初始化后处理
      initAfterHandle() {
        this.catePropertyForm.catePropertyList.forEach(e => {
          this.$set(e, 'showFlag', e.showRule.showRuleType === 1)
          this.$set(e, 'propValueAndId', '')
          this.$set(e, 'additionalPropValueAndId', '')
          this.$set(e, 'imageList', [])
          this.$set(e, 'fileLoading', false)
          if (!e.propValue) {
            this.$set(e, 'propValue', '')
          }
          if (!e.multiPropValueIds) {
            this.$set(e, 'multiPropValueIds', [])
          }
        })
        // 按顺序执行 排序 -》 rule组装
        this.sortAssemble()
        this.ruleAssemble()
      },
      // 排序组装（sortNo优先，propId次之，存在级联放于末尾，同组排序）
      sortAssemble() {
        const sortList = []
        const notConditionList = this.catePropertyForm.catePropertyList.filter(item => item.showRule.showRuleType !== 2)
        notConditionList.sort((a, b) => {
          const a_num = a.sortNo === 0 ? 0 : a.sortNo || a.propId
          const b_num = b.sortNo === 0 ? 0 : b.sortNo || b.propId
          return a_num - b_num
        })
        sortList.push(...notConditionList)

        // 构造同一组级联 内部排序
        const conditionMap = new Map()
        const conditionList = this.catePropertyForm.catePropertyList.filter(item => item.showRule.showRuleType === 2)
        conditionList.forEach(item => {
          let cascadeKey = ''
          // 条件排序
          item.showRule.showConditions.sort((a, b) => {
            return a.propId - b.propId
          })
          // 拼装key
          item.showRule.showConditions.forEach(cascade => {
            cascadeKey += cascade.propId + ':' + cascade.propValueIds.join(',') + ','
          })

          let itemList = conditionMap.get(cascadeKey)
          if (!itemList) {
            itemList = []
          }
          itemList.push(item)
          conditionMap.set(cascadeKey, itemList)
        })
        conditionMap.forEach((value, key, mapObj) => {
          sortList.push(...value)
        })
        console.log('sortAssemble before', this.catePropertyForm.catePropertyList)
        this.catePropertyForm.catePropertyList = sortList
        console.log('sortAssemble after', this.catePropertyForm.catePropertyList)
      },
      // 规则组装
      ruleAssemble() {
        const formRules = {}
        this.catePropertyForm.catePropertyList.forEach((item, index) => {
          console.log('ruleAssemble', item.propName, index)
          // 组装prop
          let baseProp = 'catePropertyList.' + index + '.'
          switch (item.propInputType) {
            case 'select':
              baseProp += 'propValueAndId'
              break
            case 'multiSelect':
              baseProp += 'multiPropValueIds'
              break
            case 'image':
              baseProp += 'imageList'
              break
            default:
              baseProp += 'propValue'
              break
          }
          this.$set(item, 'prop', baseProp)

          const itemRules = []
          const requiredFlag = item.requiredRule.requiredRuleType === 1
          if (requiredFlag) {
            itemRules.push({ required: requiredFlag, message: item.propName + '不能为空' })
          }
          switch (item.propInputType) {
            // 文本规则
            case 'text':
              var textRule = item.textRule
              var errorMsg = textRule.errorHint
              if (textRule) {
                // 正则
                if (textRule.regexps.length > 0) {
                  var pattern = ''
                  // 拼接表达式
                  textRule.regexps.forEach(regexp => {
                    pattern += regexp
                  })
                  pattern = '[' + pattern + ']'
                  // 长度限制
                  if (textRule.minLength === 0 && textRule.maxLength === 0) {
                    // 不限制
                    pattern = pattern + '*'
                  } else {
                    pattern = pattern + '{' + textRule.minLength + ',' + (textRule.maxLength > 0 ? textRule.maxLength : '') + '}'
                  }
                  itemRules.push({ pattern: new RegExp('^' + pattern + '$'), trigger: 'blur', message: errorMsg || '请输入合法字符' })
                }
                // 后置内容
                if (textRule.appendTextRule) {
                  if (requiredFlag) {
                    switch (textRule.appendTextRule.appendInputType) {
                      case 2:
                        var additionalValidator = (rule, value, callback) => {
                          return item.additionalPropValueAndId ? callback() : callback(new Error('请选择附加属性'))
                        }
                        itemRules.push({ trigger: 'blur', validator: additionalValidator })
                        break
                      default:
                        break
                    }
                  }
                }
              }
              break
            // 日期时间
            case 'datetime':
              var dateTimeRule = item.dateTimeRule
              if (dateTimeRule.rangeList && dateTimeRule.rangeList.length > 0) {
                var rangeValidator = (rule, value, callback) => {
                  var flag = true
                  if (item.propValue && item.propValue.length === 2) {
                    var startTime = item.propValue[0]
                    var endTime = item.propValue[1]
  
                    var r_0 = dateTimeRule.rangeList[0]
                    var r_1 = dateTimeRule.rangeList[1]

                    var checkStartTime = new Date(r_0).getTime()
                    var checkEndTime = dateTimeRule.rangeList.length > 1 ? new Date(r_1).getTime() : ''
                    if (startTime < checkStartTime || (checkEndTime && endTime > checkEndTime)) {
                      flag = false
                    }
                  }
                  if (flag) {
                    return callback()
                  } else {
                    var msg = item.propName + '必须在范围【' + r_0 + '-' + (r_1 || '*') + '】内'
                    return callback(new Error(msg))
                  }
                }
                itemRules.push({ trigger: 'blur', validator: rangeValidator })
              }
              break
            case 'select':
              break
            case 'multiSelect':
              break
            default:
              break
          }
          formRules[baseProp] = itemRules
        })
        this.formRules = formRules
        console.log('ruleAssemble after', formRules)
      },
      // 单选选择事件
      doSelectChange() {
        // not do 预留
      },
      // 级联下拉展示处理
      doCascadeShow(item) {
        const showConditionList = this.catePropertyForm.catePropertyList.filter(item => item.showRule.showRuleType === 2)
        if (showConditionList.length === 0) {
          return
        }
        const sourcePropId = item.propId
        const sourceValue = item.propValueAndId

        showConditionList.forEach(cateProperty => {
          const conditions = cateProperty.showRule.showConditions
          const existCascade = conditions.filter(cascadeRel => sourcePropId === cascadeRel.propId)
          // 未找到级联关系 跳过
          if (existCascade.length === 0) {
            return
          }
          if (conditions.length === 1) {
            // 单层级联
            const showFlag = sourceValue ? conditions[0].propValueIds.includes(sourceValue.split('@#')[0]) : false
            cateProperty.showFlag = showFlag
          } else {
            // 组合级联
            const showFlag = sourceValue ? existCascade[0].propValueIds.includes(sourceValue.split('@#')[0]) : false
            existCascade[0].canShowFlag = showFlag

            // 是否全满足
            const canShowCount = conditions.filter(cascadeRel => cascadeRel.canShowFlag)
            cateProperty.showFlag = canShowCount === conditions.length
          }
        })
      },
      // 超出事件
      handleExceed(file, fileList, maxCount) {
        this.$message({ type: 'warning', message: '最多可上传' + maxCount + '张' })
      },
      // 删除图片
      deleteImgages(item, index) {
        const goodsImages = item.imageList
        goodsImages.splice(index, 1)
        item.imageList = goodsImages
        this.$refs['catePropertyForm'].validateField(item.prop)
      },
      // 上传前事件
      beforeUpload(file, item) {
        const isJPG = file.type === 'image/jpeg'
        const isGIF = file.type === 'image/gif'
        const isPNG = file.type === 'image/png'
        const isBMP = file.type === 'image/bmp'
        if (!isJPG && !isGIF && !isPNG && !isBMP) {
          this.$message({ type: 'error', message: '上传图片必须是JPG/GIF/PNG/BMP 格式!' })
          return false
        }
        item.fileLoading = true
        return true
      },
      // 上传成功后事件
      handleUploadSuccess(res, file, fileList, item) {
        item.fileLoading = false
        if (res.code === 101) {
          item.imageList.push(res.data[0])
        } else {
          this.$message({ type: 'error', message: res.msg })
        }
      },
      // 保存事件
      doSave() {
        this.$refs['catePropertyForm'].validate((valid, result) => {
          if (valid) {
            console.log('form success', this.catePropertyForm.catePropertyList)
          } else {
            console.log('form error', result)
          }
        })
      }
    }
  }
</script>

<style lang="less" scoped>
  .btn {
    padding: 15px 40px;
    margin: 30px 0 0 160px;
  }
  .el-date-editor.el-input {
    width: 350px !important;
  }
  .picture {
    width: 146px;
    height: 146px;
    display: block;
  }
  .pic-bar {
    position: relative;
    display: inline-block;
    .close-icon {
      position: absolute;
      right: -30px;
      top: -11px;
      width: 31px;
      height: 40px;
      padding: 0 7px;
      cursor: pointer;
    }
    span {
      position: absolute;
      right: 0;
      bottom: 0;
      width: 100%;
      display: block;
      color: #fff;
      text-align: center;
      padding: 3px 0;
      background: rgba(0, 0, 0, 0.5);
      cursor: pointer;
    }
  }
</style>